package com.btcode.common;

public class ByteUnit {

    /**
     * 把byte转成int，针对8位的，一个byte是8位，有些由两个byte组成的数据就是16位以此类推
     */
    public static int ConvertByteToInt8(byte data) {
        int high = getHeight4(data);
        int low = getLow4(data);
        int mn = (((high & 0x00FF) << 4) | (0x00FF & low));
        return mn;
    }

    /**
     * 把高低位的byte转成double
     */
    public static double ConvertByteToDouble16(byte high, byte low) {
        double value = (double) (((high & 0x00FF) << 8) | (0x00FF & low));
        return value;
    }

    public static double ConvertByteToDouble32(byte byte1, byte byte2, byte byte3, byte byte4) {
        double value = (double) (((0xffffffff & byte4) << 24) | ((0xffffffff & byte3) << 16) | (
            (0xffffffff & byte2) << 8) | (0xffffffff & byte1));
        return value;
    }

    /**
     * 把32位的byte转成double
     * 默认顺序为：低位在前，高位在后，通过BitType类型设置读取顺序
     * 32位浮点数转换应有2种格式，
     * 一、高位在前、低位在后,ABCD：高高8位先传，再传高低8位，再传低高8位，最后传低低8位，此时100传输顺序为：0x42、0xC8、0x00、0x00
     * 二、低位在前、高位在后,ABCD：低高8位先传，再传低低8位，再传高高8位，最后传高低8位，此时100传输顺序为：0x00、0x00、0x42、0xC8
     * @param high1
     * @param low1
     * @param high2
     * @param low2
     * @return
     */
    public static double ConvertByteToDouble32_(byte high1, byte low1, byte high2, byte low2) {
        String strHex = formatNum(Integer.toHexString(high2 & 0xff)) + formatNum(
            Integer.toHexString(low2 & 0xff)) + formatNum(Integer.toHexString(high1 & 0xff))
            + formatNum(Integer.toHexString(low1 & 0xff));
        double value = getDouble32ByModbus(strHex);
        return value;
    }

    public static Double ConvertByteToDoubleX(byte[] data, BitType bitType) {

        switch (bitType) {
            case bit8:
                return (double) ConvertByteToInt8(data[0]);
            case bit16:
                return ConvertByteToDouble16(data[0], data[1]);
            case bit32:
                return ConvertByteToDouble32_(data[0], data[1], data[2], data[3]);
            case bit32_HL:
                return ConvertByteToDouble32_(data[2], data[3], data[0], data[1]);
            default:
                return null;
        }
    }

    /**
     * 取字节高位
     */
    private static int getHeight4(byte data) {//获取高四位
        int height;
        height = ((data & 0xf0) >> 4);
        return height;
    }

    /**
     * 取字节低位
     */
    private static int getLow4(byte data) {//获取低四位
        int low;
        low = (data & 0x0f);
        return low;
    }

    //根据modbus协议获得32位浮点数，读4字节
    public static Double getDouble32ByModbus(String hexstr) {
        // 先将16进制数转成二进制数0 10000001 00000000000000000000000
        String binarystr = hexString2binaryString(hexstr);
        // 1位符号位(SIGN)=0 表示正数
        String sign = binarystr.substring(0, 1);
        // 8位指数位(EXPONENT)=10000001=129[10进制]
        String exponent = binarystr.substring(1, 9);
        int expint = Integer.parseInt(exponent, 2);
        // 23位尾数位(MANTISSA)=00000000000000000000000
        String last = binarystr.substring(9);
        // 小数点移动位数
        int mobit = expint - 127;
        // 小数点右移18位后得10101001 01101001 110.00000
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 23; i++) {
            if (i == mobit) {
                sb.append(".");
            }
            char b = last.charAt(i);
            sb.append(b);
        }
        String valstr = "1" + sb.toString();
        Double dval = 0d;
        for (int i = 0; i < valstr.length(); i++) {
            if (valstr.charAt(i) == '.') {
                continue;
            }
            Double d = Math.pow(2, mobit);
            int f = Integer.parseInt(valstr.charAt(i) + "");
            d = d * f;
            mobit = mobit - 1;
            dval = dval + d;
        }
        if (sign.equals("1")) {
            dval = 0 - dval;
        }
        return dval;

    }

    public static String hexString2binaryString(String hexString) {
        if (hexString == null || hexString.length() % 2 != 0) {
            return null;
        }
        StringBuffer bString = new StringBuffer();
        for (int i = 0; i < hexString.length(); i++) {
            String tmp = "0000" + Integer.toBinaryString(
                Integer.parseInt(hexString.substring(i, i + 1), 16));
            bString.append(tmp.substring(tmp.length() - 4));
        }
        return bString.toString();
    }

    public static String formatNum(String hexStr) {
        if (hexStr.length() == 1) {
            hexStr = "0" + hexStr;
        }
        return hexStr;
    }

    public static void main(String[] args) {
        double v = ConvertByteToDouble32((byte) 0x41, (byte) 0x10, (byte) 0, (byte) 0);
        System.out.println(v);
    }

}
